package ch04;

/**
 * @author yang
 * @date 2024-04-02
 */
public class MyArrayList<E> {
    /**
     * 集合的实际大小
     */
    private int size;

    /**
     * ArrayList集合实际是对数组进行封装 - 动态数组
     */
    private Object[] elementData;

    /**
     * 数组默认长度 - 后期每次添加元素之前，都需要判断容量，按需进行扩容
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 缺省（默认）的构造方法
     */
    public MyArrayList() {
        elementData = new Object[DEFAULT_CAPACITY];
    }

    /**
     * 重载构造方法 - 用户指定数组的容量
     * @param size
     */
    public MyArrayList(int size) {
        elementData = new Object[size];
    }

    /**
     * 添加元素
     * @param e
     * @return
     */
    public boolean add(E e){
        this.elementData[size] = e ;
        ensureCapacityInternal(size + 1);
        //添加元素，size + 1
        size++;
        return true;
    }

    /**
     * 实现数组动态扩容
     * @param size
     */
    public void ensureCapacityInternal(int size){
        //动态扩容
        if (size >= elementData.length){
            //1、原来长度 + 1
            Object[] newArr = new Object[elementData.length + 1] ;

            //2、复制原数组的数据 (原数组,被复制的起始长度,新数组,覆盖的起始长度,原数组需要复制的长度)
            System.arraycopy(elementData, 0, newArr,0,elementData.length);

            elementData = newArr;
        }
    }

    /**
     * 获取集合下标对应的元素
     * @return
     */
    public E get(int index){
        //检查下标索引是否越界
        rangeCheck(index);
        return (E) elementData[index];
    }

    /**
     * 检查下标合法性
     * @param index
     */
    private void rangeCheck(int index){
        if (index < 0 || index > elementData.length){
            throw new RuntimeException("数组下标索引越界");
        }
    }

    /**
     * 判断是否为空集合
     * @return
     */
    public boolean isEmpty(){
        return this.size == 0;
    }

    /**
     * 获取集合的实际大小
     * @return
     */
    public E set(int index, E element){
        //1、检查下标索引是否越界
        rangeCheck(index);

        //2、获取被覆盖的元素
        E oldValue = (E)elementData[index];

        //3、覆盖下标索引对应的元素
        elementData[index] = element;

        //4、返回被覆盖元素
        return oldValue;
    }


    public E remove(int index){
        //1、检查下标索引是否越界
        rangeCheck(index);

        //2、获取被覆盖的元素
        E oldValue = (E)elementData[index];

        //3、覆盖下标索引对应的元素
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);


        //4、删除最后一个元素
        elementData[--size] = null; // clear to let GC do its work


        //6、返回被覆盖元素
        return oldValue;
    }

    public Object[] getElementData(){
        return this.elementData;
    }

}
